package soundsourceloc;

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import javax.swing.JFrame;
import javax.swing.JPanel;

/**
 * This class draws the direction of the source of the sound it hears.
 * 
 * It gets its from a C++ program (see companion project 'sound-source-loc')
 * 
 * @author Frederic Pesquet (fpesquet at gmail dot com)
 */
public class SoundSourceDraw extends JFrame {
	private static final long serialVersionUID = 1L;

	/** the panel that draw the last sound localization as an arc */
	private final SoundLocDraw _soundLocDraw;

	public SoundSourceDraw() throws Exception {
		super("Sound Source Localization");

		_soundLocDraw = new SoundLocDraw();
		getContentPane().add(_soundLocDraw, BorderLayout.CENTER);
	}

	/**
	 * Main loop: launch C++ listener, get its output, draw, and loop
	 * 
	 * @throws IOException
	 */
	public void run() throws IOException {
		ProcessBuilder pb = new ProcessBuilder("ssh", "pi@192.168.1.121",
				"/home/pi/sound-source-loc/src/sound-source-loc");
		pb = pb.redirectErrorStream(true);
		Process p = pb.start();
		InputStream is = p.getInputStream();
		InputStreamReader isr = new InputStreamReader(is);
		BufferedReader br = new BufferedReader(isr);
		String line;
		while ((line = br.readLine()) != null) {
			int sep = line.indexOf(';');
			try {
				float angle = Float.parseFloat(line.substring(0, sep));
				float relativePower = Float.parseFloat(line.substring(sep + 1));
				// System.out.println("received sound loc: "+line);
				_soundLocDraw.setSound(angle, relativePower);
			} catch (Exception ex) {
				System.out.println("unreadable from sound loc proc, skipping: "
						+ line);
			}
		}
	}

	/**
	 * A simple panel that draws the sound source localization angle, with a
	 * thickness depending on the sound level.
	 */
	@SuppressWarnings("serial")
	static private class SoundLocDraw extends JPanel {
		// sound angle, between -PI/2...+PI/2
		private float _angle;

		// relative power with respect to mean power (1.0=mean power)
		private float _relativePower;

		public void setSound(float angle, float relativePower) {
			_angle = angle;
			_relativePower = relativePower;
			repaint();
		}

		@Override
		protected void paintComponent(Graphics g) {
			super.paintComponent(g);
			Graphics2D g2d = (Graphics2D) g;
			Dimension d = getSize();
			int radius = Math.min(d.height, d.width / 2);
			int cx = d.width / 2;
			int cy = 0;
			int tx = cx + (int) (Math.cos(_angle + Math.PI / 2) * radius);
			int ty = cy + (int) (Math.sin(_angle + Math.PI / 2) * radius);
			g2d.drawOval(cx - radius, cy - radius, radius * 2, radius * 2);
			// use larger strokes for louder sounds:
			g2d.setStroke(new BasicStroke(1 + (int) ((Math.max(_relativePower,
					1) - 1.0) * 10)));
			g2d.drawLine(cx, cy, tx, ty);
		}
	}

	/**
	 * Entry point: create the frame, and start listening to sound until closed.
	 */
	public static void main(String[] args) throws Exception {
		SoundSourceDraw snd = new SoundSourceDraw();
		snd.setSize(800, 400);
		snd.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		snd.setLocationRelativeTo(null);
		snd.setVisible(true);
		snd.run();
	}
}
